#include "PlatformProperty.h"

MAPPING_VALUE(SeatBackrestMode, sdb::SwtHozlSts1, sdb::SwtHozlSts1::Idle)
MAPPING_ITEM(SeatBackrestMode::SEAT_BACKREST_OFF, sdb::SwtHozlSts1::Idle)
MAPPING_ITEM(SeatBackrestMode::SEAT_BACKREST_FORWARD, sdb::SwtHozlSts1::Fwd)
MAPPING_ITEM(SeatBackrestMode::SEAT_BACKREST_BACKWARD, sdb::SwtHozlSts1::Backw)
MAPPING_END
MAPPING_VALUE(sdb::SwtHozlSts1, SeatBackrestMode, SeatBackrestMode::SEAT_BACKREST_OFF)
MAPPING_ITEM(sdb::SwtHozlSts1::Idle, SeatBackrestMode::SEAT_BACKREST_OFF)
MAPPING_ITEM(sdb::SwtHozlSts1::Fwd, SeatBackrestMode::SEAT_BACKREST_FORWARD)
MAPPING_ITEM(sdb::SwtHozlSts1::Backw, SeatBackrestMode::SEAT_BACKREST_BACKWARD)
MAPPING_END

sdb::Boolean m_LastDrvrSeatExtAdjAllowd_SeatExt1 = sdb::Boolean::FALSE;
std::map<int32_t, int32_t> m_SeatAdjustmentVFCAngleMove;

static bool isMoveLimited(int32_t pos, SeatBackrestMode seatBackrestMode) {
    int32_t min = lcfg::LocalConfig::getInstance().getInt<int32_t>(lcfg::LCFG_Min_Backrest_angle);
    int32_t max = lcfg::LocalConfig::getInstance().getInt<int32_t>(lcfg::LCFG_Max_Backrest_angle);
    VHALOG.d("SEAT_BACKREST_ANGLE_1_MOVE isMoveLimited pos=%d, min=%d, max=%d seatBackrestMode=%d", pos, min, max, toInt(seatBackrestMode));
    if (seatBackrestMode == SeatBackrestMode::SEAT_BACKREST_FORWARD && pos <= min) {
        VHALOG.e("SEAT_BACKREST_ANGLE_1_MOVE can not move forward, the pos is min");
        return true;
    } else if (seatBackrestMode == SeatBackrestMode::SEAT_BACKREST_BACKWARD && pos >= max) {
        VHALOG.e("SEAT_BACKREST_ANGLE_1_MOVE can not move backward, the pos is max");
        return true;
    }
    return false;
}

void SeatAdjustmentChangeVFC_IdleToOther1(SignalTX iSignal, int32_t iValue) {
    int32_t ikey = static_cast<int32_t>(iSignal);
    std::map<int32_t, int32_t>::iterator it = m_SeatAdjustmentVFCAngleMove.find(ikey);
    int32_t idle = static_cast<int32_t>(sdb::SwtVertSts1::Idle);
    if (it == m_SeatAdjustmentVFCAngleMove.end()) {
        m_SeatAdjustmentVFCAngleMove[ikey] = idle;
    }
    VHALOG.d("SeatAdjustmentChangeVFC_IdleToOther1-iValue=%d,last=%d,Signal=%d,key=%d", iValue,
             m_SeatAdjustmentVFCAngleMove[ikey], iSignal, ikey);
    if (idle == m_SeatAdjustmentVFCAngleMove[ikey] && idle != iValue &&
        !SIGNAL.usgModeIs(sdb::UsgModSts1::UsgModAbdnd)) {
        SIGNAL.setCB_VFC_SeatComfortFunctions(sdb::OnOff1::On);
    }
    m_SeatAdjustmentVFCAngleMove[ikey] = iValue;
}

// 3.2.9 [SW_FC_004_046]第一排靠背调节1stRowSeatBackrestAdjustment--移动
SYSTEM_READ_WRITE_PROPERTY(SEAT_BACKREST_ANGLE_1_MOVE, SeatBackrestMode) {
    builder.area(VehicleAreaSeat::ROW_1_LEFT)
        .initValue([]() { return SeatBackrestMode::SEAT_BACKREST_OFF; })
        .withStatusBySignals(
            []([[maybe_unused]] const PropertyStatus& last) {
                sdb::Boolean DrvrSeatExtAdjAllowd = SIGNAL.getDrvrSeatExtAdjAllowd();
                sdb::Timeout DrvrSeatExtAdjAllowdTimeout = SIGNAL.getDrvrSeatExtAdjAllowdTimeout();
                sdb::GearLvrIndcn2 GearLvrIndcn = SIGNAL.getGearLvrIndcn();
                auto drvrSeatBtnPsd = SIGNAL.getDrvrSeatBtnPsd();
                VHALOG.d(
                    "SEAT_BACKREST_ANGLE_1_MOVE drvr status Change carmod[%d], usgmod[%d], "
                    "cc471[%d], cc1173[%d], DrvrSeatExtAdjAllowd[%d], "
                    "DrvrSeatExtAdjAllowdTimeout[%d], GearLvrIndcn[%d],drvrSeatBtnPsd[%d] ",
                    SIGNAL.getVehModMngtGlbSafe1CarModSts1(),
                    SIGNAL.getVehModMngtGlbSafe1UsgModSts(), SIGNAL.getcarconfig471(),
                    SIGNAL.getcarconfig1173(), DrvrSeatExtAdjAllowd, DrvrSeatExtAdjAllowdTimeout,
                    GearLvrIndcn, static_cast<int32_t>(drvrSeatBtnPsd));
                if (GearLvrIndcn != sdb::GearLvrIndcn2::ParkIndcn) {
                    DrvrSeatExtAdjAllowd = sdb::Boolean::FALSE;
                } else if (DrvrSeatExtAdjAllowdTimeout == sdb::Timeout::Timeout) {
                    if (SIGNAL.usgModeIs(sdb::UsgModSts1::UsgModActv, sdb::UsgModSts1::UsgModDrvg)) {
                        DrvrSeatExtAdjAllowd = sdb::Boolean::FALSE;
                    } else {
                        DrvrSeatExtAdjAllowd = m_LastDrvrSeatExtAdjAllowd_SeatExt1;
                    }
                }

                m_LastDrvrSeatExtAdjAllowd_SeatExt1 = DrvrSeatExtAdjAllowd;
                if (SIGNAL.carConfigIs(SignalRX::carconfig471,
                                       sdb::CarConfig471::_02,
                                       sdb::CarConfig471::_03) &&
                    SIGNAL.carConfigIs(SignalRX::carconfig1173, sdb::CarConfig1173::_02)) {
                    if (SIGNAL.carModeIs(sdb::CarModSts1::CarModCrash,
                                         sdb::CarModSts1::CarModDyno,
                                         sdb::CarModSts1::CarModNorm) &&
                        SIGNAL.usgModeIs(sdb::UsgModSts1::UsgModInActv,
                                         sdb::UsgModSts1::UsgModCnvinc,
                                         sdb::UsgModSts1::UsgModActv,
                                         sdb::UsgModSts1::UsgModDrvg) &&
                        DrvrSeatExtAdjAllowd == sdb::Boolean::TRUE &&
                        drvrSeatBtnPsd == sdb::Boolean::FALSE) {
                        VHALOG.d("SEAT_BACKREST_ANGLE_1_MOVE drvr Active");
                        return PropertyStatus::Active;
                    }
                    VHALOG.d("SEAT_BACKREST_ANGLE_1_MOVE drvr NotActive");
                    return PropertyStatus::NotActive;
                }
                VHALOG.d("SEAT_BACKREST_ANGLE_1_MOVE drvr NotAvailable");
                return PropertyStatus::NotAvailable;
            },
            SignalRX::carconfig471,
            SignalRX::carconfig1173,
            SignalRX::VehModMngtGlbSafe1UsgModSts,
            SignalRX::VehModMngtGlbSafe1CarModSts1,
            SignalRX::DrvrSeatExtAdjAllowd,
            SignalRX::DrvrSeatExtAdjAllowdTimeout,
            SignalRX::GearLvrIndcn,
            SignalRX::DrvrSeatBtnPsd)
        .withValueBySignals(
            []([[maybe_unused]] const SeatBackrestMode& last) {
                sdb::SwtHozlSts1 SwtSldSts = SIGNAL.getDrvrSeatSwtStsDrvrSeatSwtInclSts();
                auto angle = SIGNAL.getSeatBackAngleRowFirstDrvr();
                sdb::Boolean drvrSeatBtnPsd = SIGNAL.getDrvrSeatBtnPsd();
                VHALOG.d("GET SEAT_BACKREST_ANGLE_1_MOVE drvr DrvrSeatSwtStsDrvrSeatSwtInclSts[%d] ,angle[%d],passSeatBtnPsd[%d]",
                         SwtSldSts, angle, static_cast<int32_t>(drvrSeatBtnPsd));

                if (drvrSeatBtnPsd == sdb::Boolean::TRUE ||
                    isMoveLimited(angle, mappingValue(SwtSldSts, SeatBackrestMode::SEAT_BACKREST_OFF))) {
                    VHALOG.d("Call SEAT_BACKREST_ANGLE_1_MOVE drvr trigger to idle");
                    SeatAdjustmentChangeVFC_IdleToOther1(SignalTX::BackRestAdjmtRowFirstDrvr,
                                                         static_cast<int32_t>(sdb::SwtHozlSts1::Idle));
                    SIGNAL.setBackRestAdjmtRowFirstDrvr(sdb::SwtHozlSts1::Idle);
                    return SeatBackrestMode::SEAT_BACKREST_OFF;
                }
                return mappingValue(SwtSldSts, SeatBackrestMode::SEAT_BACKREST_OFF);
            },
            SignalRX::DrvrSeatSwtStsDrvrSeatSwtInclSts,
            SignalRX::DrvrSeatBtnPsd,
            SignalRX::SeatBackAngleRowFirstDrvr)
        .onSetProperty([](const SeatBackrestMode value) {
            if (value != SeatBackrestMode::SEAT_BACKREST_FORWARD &&
                value != SeatBackrestMode::SEAT_BACKREST_BACKWARD &&
                value != SeatBackrestMode::SEAT_BACKREST_OFF) {
                VHALOG.e("SEAT_BACKREST_ANGLE_1_MOVE drvr: param invaild");
                return;
            }
            auto angle = SIGNAL.getSeatBackAngleRowFirstDrvr();
            if (isMoveLimited(angle, value)) {
                VHALOG.e("SEAT_BACKREST_ANGLE_1_MOVE: param invaild(MoveLimited),the angle is %d", angle);
                return;
            }
            VHALOG.d("SEAT_BACKREST_ANGLE_1_MOVE drvr value is %d", value);

            sdb::SwtHozlSts1 TempBackRestAdjmtRowFirstDrvr = mappingValue(value, sdb::SwtHozlSts1::Idle);
            SeatAdjustmentChangeVFC_IdleToOther1(SignalTX::BackRestAdjmtRowFirstDrvr,
                                                 static_cast<int32_t>(TempBackRestAdjmtRowFirstDrvr));
            SIGNAL.setBackRestAdjmtRowFirstDrvr(TempBackRestAdjmtRowFirstDrvr);
        })
        .area(VehicleAreaSeat::ROW_1_RIGHT)
        .initValue([]() { return SeatBackrestMode::SEAT_BACKREST_OFF; })
        .withStatusBySignals(
            []([[maybe_unused]] const PropertyStatus& last) {
                sdb::Boolean passSeatBtnPsd = SIGNAL.getPassSeatBtnPsd();
                VHALOG.d(
                    "SEAT_BACKREST_ANGLE_1_MOVE pass status Change carmod[%d], usgmod[%d], "
                    "cc471[%d], cc1174[%d] passSeatBtnPsd[%d]",
                    SIGNAL.getVehModMngtGlbSafe1CarModSts1(),
                    SIGNAL.getVehModMngtGlbSafe1UsgModSts(), SIGNAL.getcarconfig471(),
                    SIGNAL.getcarconfig1174(), static_cast<int32_t>(passSeatBtnPsd));
                if (SIGNAL.carConfigIs(SignalRX::carconfig471,
                                       sdb::CarConfig471::_02) &&
                    SIGNAL.carConfigIs(SignalRX::carconfig1174,
                                       sdb::CarConfig1174::_02)) {
                    if (SIGNAL.carModeIs(sdb::CarModSts1::CarModCrash,
                                         sdb::CarModSts1::CarModDyno,
                                         sdb::CarModSts1::CarModNorm) &&
                        SIGNAL.usgModeIs(sdb::UsgModSts1::UsgModInActv,
                                         sdb::UsgModSts1::UsgModCnvinc,
                                         sdb::UsgModSts1::UsgModActv,
                                         sdb::UsgModSts1::UsgModDrvg) &&
                        passSeatBtnPsd == sdb::Boolean::FALSE) {
                        VHALOG.d("SEAT_BACKREST_ANGLE_1_MOVE pass  Active");
                        return PropertyStatus::Active;
                    }
                    VHALOG.d("SEAT_BACKREST_ANGLE_1_MOVE pass  NotActive");
                    return PropertyStatus::NotActive;
                }
                VHALOG.d("SEAT_BACKREST_ANGLE_1_MOVE pass  NotAvailable");
                return PropertyStatus::NotAvailable;
            },
            SignalRX::carconfig471,
            SignalRX::carconfig1174,
            SignalRX::VehModMngtGlbSafe1UsgModSts,
            SignalRX::VehModMngtGlbSafe1CarModSts1,
            SignalRX::GearLvrIndcn,
            SignalRX::PassSeatBtnPsd)
        .withValueBySignals(
            []([[maybe_unused]] const SeatBackrestMode& last) {
                sdb::SwtHozlSts1 SwtSldSts = SIGNAL.getPassSeatSwtSts2PassSeatSwtInclSts();
                auto angle = SIGNAL.getSeatBackAngleRowFirstPass();
                sdb::Boolean passSeatBtnPsd = SIGNAL.getPassSeatBtnPsd();
                VHALOG.d("withValueBySignals SEAT_BACKREST_ANGLE_1_MOVE pass PassSeatSwtSts2PassSeatSwtInclSts[%d],angle[%d] passSeatBtnPsd[%d]",
                         SwtSldSts, angle, static_cast<int32_t>(passSeatBtnPsd));

                if (passSeatBtnPsd == sdb::Boolean::TRUE ||
                    isMoveLimited(angle, mappingValue(SwtSldSts, SeatBackrestMode::SEAT_BACKREST_OFF))) {
                    VHALOG.d("Call SEAT_BACKREST_ANGLE_1_MOVE drvr trigger to idle");
                    SeatAdjustmentChangeVFC_IdleToOther1(SignalTX::BackRestAdjmtRowFirstPass,
                                                         static_cast<int32_t>(sdb::SwtHozlSts1::Idle));
                    SIGNAL.setBackRestAdjmtRowFirstPass(sdb::SwtHozlSts1::Idle);
                    return SeatBackrestMode::SEAT_BACKREST_OFF;
                }
                return mappingValue(SwtSldSts, SeatBackrestMode::SEAT_BACKREST_OFF);
            },
            SignalRX::PassSeatSwtSts2PassSeatSwtInclSts,
            SignalRX::PassSeatBtnPsd,
            SignalRX::SeatBackAngleRowFirstPass)
        .onSetProperty([](const SeatBackrestMode value) {
            if (value != SeatBackrestMode::SEAT_BACKREST_FORWARD &&
                value != SeatBackrestMode::SEAT_BACKREST_BACKWARD &&
                value != SeatBackrestMode::SEAT_BACKREST_OFF) {
                VHALOG.e("SEAT_BACKREST_ANGLE_1_MOVE pass: param invaild");
                return;
            }
            auto angle = SIGNAL.getSeatBackAngleRowFirstPass();
            if (isMoveLimited(angle, value)) {
                VHALOG.e("SEAT_BACKREST_ANGLE_1_MOVE: param invaild(MoveLimited),the angle is %d", angle);
                return;
            }
            VHALOG.d("SEAT_BACKREST_ANGLE_1_MOVE pass value is %d", value);
            sdb::SwtHozlSts1 TempBackRestAdjmtRowFirstPass = mappingValue(value, sdb::SwtHozlSts1::Idle);
            SeatAdjustmentChangeVFC_IdleToOther1(SignalTX::BackRestAdjmtRowFirstPass,
                                                 static_cast<int32_t>(TempBackRestAdjmtRowFirstPass));
            SIGNAL.setBackRestAdjmtRowFirstPass(TempBackRestAdjmtRowFirstPass);
        });
}